//-----------------------------------------------------------------------------
// Name: Display.cpp
// Auth: Bradford J. Smith & Robert Darty
// Desc: methods and data for display
//-----------------------------------------------------------------------------

#include <windows.h>
#include "Display.h"
#include "CollisionDetect.h"
#include "Assert.h"
#include "DisplayManager.h"
#include "SharedConstants.h"
#include "Systems.h"
#include "RobTown.h"
#include "AnimateObject.h"
#include "AnimateObjectManager.h"
#include "InanimateObject.h"
#include "InanimateObjectManager.h"
#include "rifle.h"
#include "Bullet.h"
#include "BulletManager.h"
#include "Gun.h"
#include "GunManager.h"
#include <iostream>
#include "corona/corona.h"
#include "Barn.h"
#include "DeadHuman.h"
#include "DeadCow.h"

using namespace std;
//-----------------------------------------------------------------------------
// Globals:
//-----------------------------------------------------------------------------
DWORD gLastTickCount = 0;

int gDead;

const int kElapsedMSHistorySize = 30;
std::list< int > gElapsedMSHistory;

//-----------------------------------------------------------------------------
// Constants:
//-----------------------------------------------------------------------------
//static const DWORD kUpdateTimeMS = 200;

//-----------------------------------------------------------------------------
// Function Definitions:
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------

void DrawFPSCounter()
{
	// change to a simple 2D perspective for rendering text
	glDisable(GL_DEPTH_TEST);
	glDisable(GL_LIGHTING);
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	{
		glLoadIdentity();
		glMatrixMode(GL_PROJECTION);
		glPushMatrix();
		{
			glLoadIdentity();
			glOrtho(0.0f, GetDisplayManager()->GetWindowWidth(), 0.0f, GetDisplayManager()->GetWindowHeight(), -1.0f, 1.0f);


			static DWORD lastTick = 0;
			int elapsedTimeMS = (int)(GetTickCount() - lastTick);
			gElapsedMSHistory.push_back(elapsedTimeMS);

			// maintain the size of the list.
			if (gElapsedMSHistory.size() > kElapsedMSHistorySize)
			{
				gElapsedMSHistory.pop_front();
			}

			// only do the math and display once we've filled the history
			int historySize = (int)gElapsedMSHistory.size();
			if (historySize == kElapsedMSHistorySize)
			{
				// average the milliseconds per frame
				float totalElapsedMS = 0.0f;
				std::list< int >::iterator iter = gElapsedMSHistory.begin();
				std::list< int >::iterator listEnd = gElapsedMSHistory.end();
				for (iter; iter != listEnd; ++iter)
				{
					totalElapsedMS += *iter;
				}
				float averageMSPF = totalElapsedMS / historySize;

				float averageFPS = historySize / (totalElapsedMS / 1000.0f);

				lastTick = GetTickCount();

				// fps counter
				static int frames = 0;
				static int lastframes = 0;
				frames++;
				static DWORD lastcheck = 0;
				if (GetTickCount() - lastcheck >= 1000)
				{
					lastframes = frames;
					frames = 0;
					lastcheck = GetTickCount();
				}
				glColor3fv(kColorBlack);
				glRasterPos2i(175, GetDisplayManager()->GetWindowHeight() - 10);
				char buff[64];
				sprintf_s(buff, 64, "%.1f FPS %.1f MSPF", averageFPS, averageMSPF);
				for (unsigned int i = 0; i < strlen(buff);i++)
				{
					glutBitmapCharacter(GLUT_BITMAP_9_BY_15, buff[i]);
				}
			}
		}
		glPopMatrix();
	}
	glMatrixMode(GL_MODELVIEW);
	glPopMatrix();
	glEnable(GL_LIGHTING);
}
void ReshapeFunction(GLsizei w, GLsizei h)
{
	// update the data in the display manager
	cDisplayManager* pDisplayManager = GetDisplayManager();
	pDisplayManager->SetWindowArea(w, h);

	// update the viewport within the window
	glViewport(0, 0, w, h);

	pDisplayManager->UpdateProjection();
}

//-----------------------------------------------------------------------------
void DisplayFunction()
{
	cDisplayManager* pDisplayManager = GetDisplayManager();
	Assert(pDisplayManager != NULL);

	// clear the buffers
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	//calculates the time elapsed since last frame
	int elapsedTimeMS = (int)(GetTickCount() - gLastTickCount);

	//Overrides for long times - mainly takes out a bug at game start
	if (elapsedTimeMS > 1600)
	{
		elapsedTimeMS = 1600;
	}
	float elapsedTimeS = (float)elapsedTimeMS / 1000.0f;
	gLastTickCount = GetTickCount();

	//Draws the HUD - should always be drawn first!
	pDisplayManager->DrawHUD(elapsedTimeS);

	//Display FPS
	//DrawFPSCounter();

	//If we're alive and haven't won
	if(pDisplayManager->GetStatus() && !(pDisplayManager->GetVictory()))
	{
		int area = CheckArea(pDisplayManager->GetCameraX(), pDisplayManager->GetCameraZ())-1;
		
		// Updates the camera - including all movement by player
		pDisplayManager->UpdateCamera(elapsedTimeS);	

		// draw the town
		cRobTown* pRobTown = GetRobTown();
		if (pRobTown)
		{
			pRobTown->Draw();
		}


		cAnimateObjectManager* pAnimateObjectManager = GetAnimateObjectManager();

		//If boss hasn't been activated
        if(pAnimateObjectManager->GetBoss()==false)
		{
			pAnimateObjectManager->AnimateAI(area);
			pAnimateObjectManager->UpdateAnimateObject(elapsedTimeS, area);
		
			
		}
		else
		{
			//Set up boss
			if(pAnimateObjectManager->GetBossSetup()==true)
			{
				pAnimateObjectManager->AddBoss();
				pAnimateObjectManager->SetBossSetup(false);
			}
			//Animate all boss stuff
			else
			{
				pAnimateObjectManager->BossAnimateAI(elapsedTimeS);
				pAnimateObjectManager->UpdateAnimateBossObjects(elapsedTimeS);
				bool victory = pAnimateObjectManager->CheckVictory();
				//Check for victory
				if(victory)
				{
					pDisplayManager->SetVictory(true);
				}
			}
		
		}
		//Remove dead animates
		pAnimateObjectManager->RemoveAnimateObject(elapsedTimeS, area);
		cInanimateObjectManager* pInanimateObjectManager = GetInanimateObjectManager();

		//Update inanimates (really just draws them)
		pInanimateObjectManager->UpdateInanimateObject(elapsedTimeS);
		
	
		cGunManager* pGunManager = GetGunManager();
		//Set gun position relative to player
		pGunManager->SetPositions(pDisplayManager->GetCameraX(),pDisplayManager->GetCameraY(), pDisplayManager->GetCameraZ(), pDisplayManager->GetCameraHeading(), pDisplayManager->GetCameraPitch());
		pGunManager->Draw();
		
		cBulletManager* pBulletManager = GetBulletManager();

		//Update bullets
		pBulletManager->updateBullets(elapsedTimeS);
		
		//remove bullets
		pBulletManager->removeBullet();

		//Sets which collision checking is active
		if(pAnimateObjectManager->GetBoss()==false)
		{
			CheckCollisions(elapsedTimeS, area);
		}
		else
		{
			CheckBossCollisions(elapsedTimeS);
		}

		//LOTS OF BARN DRAWING
	for ( int j = -100; j < 110; j+=40 )
	{
		cBarn* pBarn = GetBarn();
		pBarn->Move( (float) j, -152.5 );
		pBarn->Rotate( 0.0f );
		if (pBarn)
		{
			pBarn->Draw();
		}
	}

	for ( int j = -80; j < 140; j+=40 )
	{
		cBarn* pBarn = GetBarn();
		pBarn->Move( (float) j, -118.5 );
		pBarn->Rotate( 180.0f );
		if (pBarn)
		{
			pBarn->Draw();
		}
	}


	for ( int j = -190; j < -50; j+=40 )
	{
		cBarn* pBarn = GetBarn();
		pBarn->Move( 207.5f, (float) j );
		pBarn->Rotate( -90.0f );
		if (pBarn)
		{
			pBarn->Draw();
		}
	}


	for ( int j = -40; j < 80; j+=40 )
	{
		cBarn* pBarn = GetBarn();
		pBarn->Move( 212.5f, (float) j );
		pBarn->Rotate( -90.0f );
		if (pBarn)
		{
			pBarn->Draw();
		}
	}

	for ( int j = -90; j < 90; j+=40 )
	{
		cBarn* pBarn = GetBarn();
		pBarn->Move( -217.5f, (float) j );
		pBarn->Rotate( 90.0f );
		if (pBarn)
		{
			pBarn->Draw();
		}
	}

	for ( int j = 140; j < 230; j+=40 )
	{
		cBarn* pBarn = GetBarn();
		pBarn->Move( -172.5f, (float) j );
		pBarn->Rotate( 90.0f );
		if (pBarn)
		{
			pBarn->Draw();
		}
	}

	for ( int j = -60; j < 120; j+=40 )
	{
		cBarn* pBarn = GetBarn();
		pBarn->Move( (float) j, 212.5f );
		pBarn->Rotate( 180.0f );
		if (pBarn)
		{
			pBarn->Draw();
		}
	}

	for ( int j = -170; j < -80; j+=40 )
	{
		cBarn* pBarn = GetBarn();
		pBarn->Move( (float) j, -67.5f );
		pBarn->Rotate( 180.0f );
		if (pBarn)
		{
			pBarn->Draw();
		}
	}

	for ( int j = 65; j < 130; j+=40 )
	{
		cBarn* pBarn = GetBarn();
		pBarn->Move( -127.5f, (float) j );
		pBarn->Rotate( 270.0f );
		if (pBarn)
		{
			pBarn->Draw();
		}
	}

	for ( int j = 140; j < 200; j+=40 )
	{
		cBarn* pBarn = GetBarn();
		pBarn->Move( (float) j, 162.5f );
		pBarn->Rotate( 180.0f );
		if (pBarn)
		{
			pBarn->Draw();
		}
	}

	
	 static int sTime = (int) ( GetTickCount() + 100000 ) % 10000000 / 1000;

	int iTemp = sTime - (int) GetTickCount() % 10000000 / 1000;

	if ( iTemp )//> 50 )
	{
		cDeadHuman* pDeadHuman = GetDeadHuman();

		pDeadHuman->Draw();
	}

	if ( iTemp )
	{
		cDeadCow* pDeadCow = GetDeadCow();

		pDeadCow->Draw();
	}

	}

	// flip the buffer to the screen
	glFlush();
	glutSwapBuffers();
}

DWORD GetGLastTickCount()
{
	return gLastTickCount;
}

